package com.github.jokar.customizeview.widget

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.support.v4.content.ContextCompat
import android.text.TextPaint
import android.util.AttributeSet
import android.view.View
import com.github.jokar.customizeview.R

/**
 * Created by JokAr on 2017/10/23.
 */
class LikeView @JvmOverloads constructor(context: Context,
                                         attrs: AttributeSet?,
                                         defStyleAttr: Int)
    : View(context, attrs, defStyleAttr) {
    constructor(context: Context, attrs: AttributeSet? = null) : this(context, attrs, 0)
    constructor(context: Context) : this(context, null)

    /**
     * 点赞时，图标有一个缩小扩大再回缩的动作，这两个常量表示缩放时的最大和最小倍数
     */
    private val EXPAND_MULTIPLE = 1.5f
    private val SHRINK_MULTIPLE = 0.8f
    /**
     * 动画持续时间 ms
     */
    val DURATION = 300L
    //图标
    private var drawableSelect: Drawable? = null
    private var drawableUnSelect: Drawable? = null
    private var drawableShining: Drawable? = null
    /**
     * 图标大小 dp
     */
    private var iconSize: Int = 20

    /**
     * 是否已赞
     */
    var hasLike = false


    private var textPaint: TextPaint = TextPaint()
    /**
     * 飘出字体
     */
    private var oldTextPaint: TextPaint = TextPaint()
    private var newTextPaint: TextPaint = TextPaint()
    /**
     * 画圆
     */
    private var circlePaint: Paint = Paint()

    /**
     * 文字大小
     */
    private var textSize = 12
    /**
     * 文字宽度
     */
    private var textWidth = 0f
    /**
     * 共同部分宽度
     */
    private var commonTextWidth = 0f
    /**
     *  闪光图标的大小
     */
    private var shiningSize = 0
    /**
     * 文字高度
     */
    private var textHeight = 0f
    private var textBound: Rect = Rect()
    var likeCount = 4189
        set(value) {
            field = value
            postInvalidate()
        }
    /**
     * 是否已分割数字
     */
    var hasCutNum = false
    /**
     * 相同部分数字
     */
    var commonNum = ""
    /**
     * 不同部分数字 - 旧
     */
    var oldNum = ""
    /**
     * 不同部分数字 - 新
     */
    var newNum = ""
    /**
     * 图片与文本的间距
     */
    private var spacing = 10
    /**
     * 点赞时图标扩大需要的补充大小
     */
    private var iconSizeAdditional = 0
    /**
     * 圆的圆心坐标
     */
    private var circleStartX = 0f
    private var circleStartY= 0f

    private var animatorSet: AnimatorSet? = null
    /**
     * icon的缩放级别
     */
    private var iconScale = 1f
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_IconScale = "iconScale"
    /**
     * icon 未喜欢的缩放级别
     */
    private var iconUnLikeScale = 1f
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_IconUnLikeScale = "iconUnLikeScale"
    /**
     * 闪光缩放级别
     */
    private var shiningScale = 1f
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_ShiningScale = "shiningScale"
    /**
     * 新旧数字偏移量
     */
    private var numberOffset = 0f
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_NumberOffset = "numberOffset"
    /**
     * 旧数字 透明度
     */
    private var oldNumberAlpha = 255
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_OldNumberAlpha = "oldNumberAlpha"
    /**
     * 新数字部分 透明度
     */
    private var newNumberAlpha = 0
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_NewNumberAlpha = "newNumberAlpha"

    private var circleRadius = 0f
        set(value) {
            field = value
            postInvalidate()
        }
    val LikeView_CircleRadius = "circleRadius"

    //
    init {
        val typeArray = context.obtainStyledAttributes(attrs, R.styleable.LikeView, defStyleAttr, 0)
        iconSize = typeArray.getDimensionPixelSize(R.styleable.LikeView_iconSize, dip2px(iconSize))
        textSize = typeArray.getDimensionPixelSize(R.styleable.LikeView_textSize, sp2px(textSize))
        typeArray.recycle()

        //计算闪光图标大小
        shiningSize = (0.8 * iconSize).toInt()
        //
        textPaint.isAntiAlias = true
        textPaint.textSize = textSize.toFloat()
        textPaint.color = Color.parseColor("#bdc3c7")

        //
        oldTextPaint.isAntiAlias = true
        oldTextPaint.textSize = textSize.toFloat()
        oldTextPaint.color = Color.parseColor("#bdc3c7")
        //
        newTextPaint.isAntiAlias = true
        newTextPaint.textSize = textSize.toFloat()
        newTextPaint.color = Color.parseColor("#bdc3c7")
        //
        circlePaint.strokeWidth = 3.5f
        circlePaint.isAntiAlias = true
        circlePaint.style = Paint.Style.STROKE
        circlePaint.color = Color.parseColor("#E4583E")
        //获得补充大小
        iconSizeAdditional = ((EXPAND_MULTIPLE - 1) * iconSize).toInt()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        val likeText = "$likeCount"
        //获取文字宽度
        textPaint.getTextBounds(likeText, 0, likeText.length, textBound)
        textWidth = textPaint.measureText(likeText)
        textHeight = textBound.height().toFloat()
        //获得共同文本宽度
        if (hasCutNum && !hasCutNum.equals("0")) {
            commonTextWidth = textPaint.measureText(commonNum)
        }
        //
        val width = (EXPAND_MULTIPLE * iconSize) + textWidth + paddingLeft + paddingRight + spacing
        val height = paddingBottom + paddingTop + iconSize + shiningSize
        setMeasuredDimension(width.toInt(), height)

        //赋值icon资源
        prepareSource()
        //
        //画圆
        circleStartX = ((paddingLeft + iconSize + spacing + iconSizeAdditional) / 2 + 5).toFloat()
        circleStartY = ((paddingTop + shiningSize + iconSize) / 2 - 5).toFloat()
    }


    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        //画图标
        drawIcon(canvas)
        //画数字
        drawNumber(canvas)
    }

    /**
     * 画数字
     */
    private fun drawNumber(canvas: Canvas) {
        if (!hasCutNum) {
            canvas.drawText("$likeCount",
                    (paddingLeft + spacing + iconSize + iconSizeAdditional).toFloat(),
                    height / 2 + textHeight / 2,
                    textPaint)
        } else {
            newTextPaint.alpha = newNumberAlpha
            oldTextPaint.alpha = oldNumberAlpha
            if (hasLike) numberOffset *= -1
            //先画共同部分
            canvas.drawText(commonNum,
                    (paddingLeft + spacing + iconSize + iconSizeAdditional).toFloat(),
                    height / 2 + textHeight / 2,
                    textPaint)

            //再画旧的数字
            canvas.drawText(oldNum,
                    paddingLeft + spacing + iconSize + iconSizeAdditional + commonTextWidth,
                    height / 2 + textHeight / 2 + numberOffset,
                    oldTextPaint)
            //最后新的数字
            if (!hasLike) {
                canvas.drawText(newNum,
                        paddingLeft + spacing + iconSize + iconSizeAdditional + commonTextWidth,
                        paddingTop + textHeight + numberOffset,
                        newTextPaint)
            } else {
                canvas.drawText(newNum,
                        paddingLeft + spacing + iconSize + iconSizeAdditional + commonTextWidth,
                        height - paddingBottom + numberOffset,
                        newTextPaint)
            }

        }
    }

    /**
     * 画图标
     */
    private fun drawIcon(canvas: Canvas) {

        if (hasLike) {
            val scaleSize: Int = (iconSize * (1 - iconScale) / 2).toInt()
            drawableSelect?.setBounds(
                    paddingLeft + iconSizeAdditional + scaleSize,
                    paddingTop + shiningSize / 2 + scaleSize,
                    iconSize + paddingLeft + iconSizeAdditional - scaleSize,
                    paddingTop + shiningSize / 2 + iconSize - scaleSize
            )
            drawableSelect?.draw(canvas)
            //画闪光
            val shiningScale: Int = (shiningSize * (1 - shiningScale) / 2).toInt()

            drawableShining?.setBounds(
                    paddingLeft + (iconSize - shiningSize) / 2 + iconSizeAdditional + shiningScale,
                    paddingTop + shiningScale,
                    paddingLeft + (iconSize - shiningSize) / 2 + shiningSize + iconSizeAdditional - shiningScale,
                    paddingTop + shiningSize - shiningScale
            )
            drawableShining?.draw(canvas)

            circlePaint.alpha = oldNumberAlpha
            canvas.drawCircle(circleStartX,
                    circleStartY,
                    circleRadius,
                    circlePaint)
        } else {
            val scaleSize: Int = (iconSize * (1 - iconUnLikeScale) / 2).toInt()
            drawableUnSelect?.setBounds(
                    paddingLeft + iconSizeAdditional + scaleSize,
                    paddingTop + shiningSize / 2 + scaleSize,
                    iconSize + paddingLeft + iconSizeAdditional - scaleSize,
                    paddingTop + shiningSize / 2 + iconSize - scaleSize
            )
            drawableUnSelect?.draw(canvas)
        }
    }

    /**
     * 赋值icon资源
     */
    private fun prepareSource() {
        if (hasLike) {
            if (drawableSelect == null) {
                drawableSelect = ContextCompat.getDrawable(context, R.mipmap.ic_like_selected)
            }
            if (drawableShining == null) {
                drawableShining = ContextCompat.getDrawable(context, R.mipmap.ic_like_selected_shining)
            }
        } else {
            if (drawableUnSelect == null) {
                drawableUnSelect = ContextCompat.getDrawable(context, R.mipmap.ic_like_unselected)
            }
        }
    }

    private fun startAnimatorSet() {
        if (animatorSet != null && animatorSet!!.isRunning) {
            animatorSet?.cancel()
        }

        //取消点赞时- icon动画
        val animator1 = ObjectAnimator.ofFloat(this, LikeView_IconUnLikeScale,
                SHRINK_MULTIPLE, 1f)
        //点赞时 - icon动画
        val animator2 = ObjectAnimator.ofFloat(this, LikeView_IconScale, SHRINK_MULTIPLE,
                EXPAND_MULTIPLE, 1f)
        //点赞时 - 闪光动画
        val animator3 = ObjectAnimator.ofFloat(this, LikeView_ShiningScale, 0f, 1f)
        //数字替换的位移动画
        val animator4 = ObjectAnimator.ofFloat(this, LikeView_NumberOffset, 0f,
                (iconSize + shiningSize - textHeight) / 2)
        //
        val animator5 = ObjectAnimator.ofInt(this, LikeView_OldNumberAlpha,
                255, 0)
        val animator6 = ObjectAnimator.ofInt(this, LikeView_NewNumberAlpha,
                0, 255)
        //点赞时-最外层圆
        val animator7 = ObjectAnimator.ofFloat(this,
                LikeView_CircleRadius,
                (iconScale + shiningSize) / 4 * 3,
                (iconScale + shiningSize) / 8 * 7.5f)
//        animator7.startDelay = 100
        //
        animatorSet = AnimatorSet()
        animatorSet?.duration = DURATION
        animatorSet?.addListener(object : AnimatorListenerAdapter() {
            override fun onAnimationEnd(animation: Animator?) {
                super.onAnimationEnd(animation)
                hasCutNum = false
            }

            override fun onAnimationCancel(animation: Animator?) {
                super.onAnimationCancel(animation)
                hasCutNum = false
            }
        })
        //
        if (hasLike) {
            animatorSet?.playTogether(animator2, animator3, animator4, animator5, animator6, animator7)
        } else {
            animatorSet?.playTogether(animator1, animator4, animator5, animator6)
        }
        animatorSet?.start()
    }

    fun start(like: Boolean) {
        hasLike = like
        //分割数字
        cutNum(like)
        startAnimatorSet()
    }

    /**
     * 分割数字
     */
    private fun cutNum(like: Boolean) {
        var oldNumber = "$likeCount"

        if (like) {
            likeCount++
        } else {
            likeCount--
        }
        //
        val numberText = "$likeCount"
        val index = (0..numberText.length).firstOrNull {
            numberText[it] != oldNumber[it]
        } ?: 0
        //
        commonNum = numberText.substring(0, index)
        oldNum = oldNumber.substring(index)
        newNum = numberText.substring(index)
        println("commonNum: $commonNum, oldNum: $oldNum, newNum: $newNum")
        //
        hasCutNum = true

        invalidate()
        requestLayout()
    }

    /**
     * sp px转换
     */
    fun sp2px(spValue: Int): Int {
        val fontScale = context.resources.displayMetrics.scaledDensity
        return (spValue * fontScale + 0.5f).toInt()
    }

    /**
     * dp px转换
     */
    fun dip2px(dipValue: Int): Int {
        val scale = context.resources.displayMetrics.density
        return (dipValue * scale + 0.5f).toInt()
    }
}